home *** CD-ROM | disk | FTP | other *** search
- /************************************************
- **
- ** *** HAPPy P-code Interpreter ***
- **
- ** メイン処理
- **
- ** Copyright (c) H.Asano. 1992-1994.
- ************************************************/
-
- #define EXTERN
-
- #include <signal.h>
- #include <process.h>
- #include <io.h>
- #include <conio.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <float.h>
- #include "version.h"
- #include "hapai.h"
-
- #define abnormal 1 /* usage関数への引数 */
- #define normal 0 /* usage関数への引数 */
-
- extern void interpret(void) ; /* P-code命令解釈実行処理 */
-
- _store store[Maxstore] ; /* 記憶装置 */
-
- _store *sp ; /* stack pointer */
- short pc ; /* program counter */
- short mp ; /* begginning of a data segment */
- short ep ; /* the maxmum extent of the stack */
- short np ; /* top of the dynamically allocated area */
-
- _code cd ; /* P-code */
-
- short fileno ; /* ファイル数 */
-
- boolean trace ; /* 命令トレースフラグ */
- boolean readlnflag = true ; /* 起動時及びinputにreadlnをした時 真 */
-
- const char *ext = ".pco" ; /* P-codeオプジェクトファイルの拡張子 */
- static char pcofname[50] ; /* P-codeオブジェクトファイル名 */
- static char progname[33] ; /* Pascalプログラム名 */
-
- static short objsize ;
- static FILE *pcofile ;
- static boolean infor = false ; /* -iオプション インタプリタ情報出力 */
- static boolean fileoptflag = false ; /* /fオプション ファイル名指定 */
- static short fno ; /* /fオプションで取得したファイル数 */
- static int wargc ; /* argc 退避 */
- static char **wargv ; /* argv 退避 */
-
- /******************************************/
- /* puteoln() : 終了時のeoln付与処理 */
- /******************************************/
- void puteoln(void)
- {
- short i ;
-
- for(i=0;i<fileno;i++) { /* ファイルクローズを行う */
- if((fi[i].mode == generation) && /* 生成モードでテキストで */
- (fi[i].textfile) && (!fi[i].writelnflag)) /* 最後が改行でない*/
- fputc('\n',fi[i].fp) ; /* 改行を付け加える */
- fclose(fi[i].fp) ; /* エラーチェックはしない */
- }
- }
-
- /******************************/
- /* title() : タイトル表示処理 */
- /******************************/
- static void title(void)
- {
- static putflag = false ;
-
- if(!putflag) { /* 一度だけ表示する */
- fprintf(stderr,
- "HAPPy P-code Interpreter Version %s Copyright (c) H.Asano 1992-1994.\n",
- version) ;
- putflag = true ;
- }
- }
-
- /******************************************/
- /* prerr() : Run-timeエラーメッセージ出力 */
- /******************************************/
- void prerr(short errno,char *msg)
- {
- fprintf(stderr,"\n*** [ADDR=%d] HAPPy Run-time error R%03d:\n -- %s",
- pc-1,errno,msg) ;
- fputs(" : 処理打ち切り ***\n",stderr);
- puteoln() ; /* ファイルクローズ & eoln付与*/
- exit(1) ; /* ランタイムエラーで終了 */
- }
-
- /**********************************************/
- /* pierr() : インタプリタエラーメッセージ出力 */
- /**********************************************/
- static void pierr(char *msg, char *umecomi)
- {
- title() ;
- fprintf(stderr,msg,umecomi) ;
- exit(2) ; /* その他のエラーで終了 */
- }
-
- /****************************************/
- /* cntl_c(): cntl_cが押された時の処理 */
- /****************************************/
- static void cntl_c(int sig, int subcode)
- {
- prerr(152,"<CTRL-C>を受け付けた");
- }
-
- /****************************************/
- /* real_err(): 浮動小数点例外 */
- /****************************************/
- static void real_err(int sig, int subcode)
- {
- char *type ;
- char buf[80] ;
-
- switch(subcode) {
- case FPE_INVALID : type = "invalid"; break ;
- case FPE_OVERFLOW : type = "overflow"; break ;
- case FPE_STACKOVERFLOW : type = "stack overflow"; break ;
- case FPE_STACKUNDERFLOW : type = "stack underflow"; break ;
- }
- sprintf(buf,"実数演算で異常が起きた(%s)",type) ;
- prerr(150,buf) ;
- }
-
- /******************************/
- /* usage() : 使用方法出力処理 */
- /******************************/
- static void usage(short type)
- {
- title() ;
- if(type==abnormal) fputs("\nI004: 起動パラメータが誤っている\n",stderr);
- else { /* pi のみで アーギュメントなしの時 */
- fputs("\n HAPPy is the H.Asano Pascal Processing system. (^_^)\n",
- stderr);
- fputs(
- "\n HAPPyはISO7185規格水準0にほぼ準拠したMS-DOS汎用Pascal処理系です。\n",
- stderr) ;
- fputs(" HAPPyの複写・再配付は自由です。\n", stderr) ;
- }
-
- fputs("\n piコマンドはpcコマンドで作ったP-codeオブジェクトを実行します。\n\n",stderr);
-
- fputs(" 使い方: pi [ オプション...] P-codeオブジェクトファイル名[.pco] [ オプション...]\n",
- stderr) ;
- fputs(" オプション:\n",stderr);
- fputs(" -i ・・・ インタプリタ情報を出力する\n",stderr);
- fputs(" -t ・・・ トレースをを標準出力に出力する\n",stderr);
- fputs(" /f ・・・ プログラム引数のファイル名と実ファイル名を対応させる\n",
- stderr);
- fputs(" 例: /fputfile=h:\\work\\list.txt\n",stderr) ;
-
- exit(2) ;
- }
-
- /************************************/
- /* information() : -iオプション処理 */
- /************************************/
- static void information(void)
- {
- short i,j ;
- short max = 0 ;
-
- title() ;
- fprintf(stderr,"\n * Program name = %s\n",progname) ;
- fprintf(stderr," * Total memory = %5d words\n",Maxstore) ;
- fprintf(stderr," * Object size = %5d words\n",objsize) ;
- fprintf(stderr," * stack/heap = %5d words\n",Maxstore-objsize) ;
- if(fileno!=2) {
- fputs(" * input,output以外のファイルと実ファイルの対応\n",stderr) ;
- for(i=2;i<fileno;i++)
- if(strlen(fi[i].filename) > max) max = strlen(fi[i].filename) ;
- for(i=2;i<fileno;i++) {
- fprintf(stderr," %s",fi[i].filename) ;
- for(j=strlen(fi[i].filename);j<max;j++)
- fputc(' ',stderr) ; /* 最大の長さに合わせるため */
- fprintf(stderr," = %s\n",fi[i].rfname) ;
- }
- }
- fputc('\n',stderr) ;
- }
-
- /******************************************/
- /* fileoption() : ファイルオプション処理 */
- /******************************************/
- static void fileoption(char *fileopt)
- {
- short i=0 ;
- short j ;
- short len ;
- char logicalf[MaxIDlng+1] ; /* プログラム上のファイル名 */
-
- if(fileno==2) usage(abnormal) ; /* ファイル未使用時 /f は 指定不可*/
-
- while(*(fileopt+i)!='=') i++ ; /* プログラム上のファイル名取得*/
- if(i>MaxIDlng) i=MaxIDlng ;
- for(j=0;j<i;j++)
- logicalf[j] = (char)tolower(*(fileopt+j)) ;
- logicalf[i] = '\0' ;
-
- j=2;
- while((j<fileno) &&
- strcmp(fi[j].filename,logicalf)) j++ ;
- if(j==fileno) { /* プログラム上で使われていない時*/
- title() ;
- fprintf(stderr,"I005:/fオプション(%s)無効 : 無視する\n",fileopt) ;
- return ;
- }
- if(fi[j].askflag) { /* まだ/fオプションで未処理のファイル */
- fi[j].askflag = false ;
- fno++ ; /* /fオプション で 指定したファイル数 */
- }
- len = strlen(fileopt)-i-1 ;
- if(len > MaxRFlen) len = MaxRFlen ;
- strncpy(fi[j].rfname,fileopt+i+1,len) ;
- fi[j].rfname[len] = '\0' ;
- }
-
- /*****************************************/
- /* inputfilename() : ファイル名入力処理 */
- /*****************************************/
- static void inputfilename(void)
- {
- short i,j ;
- short ch ;
-
- title() ;
- fputs("*HAPPy: ファイル( ",stderr) ;
- for(i=2;i<fileno;i++)
- if(fi[i].askflag) fprintf(stderr,"%s ",fi[i].filename) ;
- fputs(")の実ファイル名を入力して下さい\n",stderr);
-
- for(i=2;i<fileno;i++)
- if(fi[i].askflag) {
- fprintf(stderr," %s : ",fi[i].filename) ;
- while(((ch=getc(stdin)) == ' ') || (ch == '\t'));
- /* 空白,タブの読み飛ばし */
- j = 0 ;
- while(ch != '\n') {
- fi[i].rfname[j++] = (char)ch ;
- if(j == MaxRFlen) break ;
- ch = getc(stdin) ;
- } ;
- fi[i].rfname[j] = '\0' ;
- }
- fputs("*HAPPy: ファイル名入力終了 *\n\n",stderr) ;
- }
-
- /***************************************/
- /* fcheck() : ファイルチェック処理 */
- /***************************************/
- static void fcheck(void)
- {
- if(feof(pcofile)) /* 途中でファイルが終わってしまった*/
- pierr("I002: P-codeオブジェクトファイル(%s)が不当である",pcofname) ;
- }
-
- /***************************************/
- /* init() : 初期設定処理 */
- /***************************************/
- static void init(void)
- {
- short i ;
- char ch ;
- short headerlen ; /* ヘッダ部分の長さ */
- char compversion[6] ; /* コンパイラバージョン番号 */
-
- /**** input,outputファイルのファイル情報を設定する ****/
-
- strcpy(fi[0].filename,"input") ;
- fi[0].fileadr = inputadr ;
- fi[0].filesize = 1 ;
- strcpy(fi[0].rfname,"標準入力") ;
- fi[0].fp = stdin ; /* 標準入力 */
- fi[0].mode = inspection ; /* 検査モード */
- fi[0].textfile = true ; /* テキストファイル */
-
- strcpy(fi[1].filename,"output") ;
- fi[1].fileadr = outputadr ;
- fi[1].filesize = 1 ;
- strcpy(fi[1].rfname,"標準出力") ;
- fi[1].fp = stdout ; /* 標準出力 */
- fi[1].mode = generation ; /* 生成モード */
- fi[1].textfile = true ; /* テキストファイル */
- fi[1].writelnflag = true ;
-
- fileno = fno = 2 ;
-
- objsize = (short)filelength(fileno(pcofile));
- i = 0 ;
- do { /* バージョン番号を読む */
- ch = (char)fgetc(pcofile) ;
- fcheck() ;
- } while((compversion[i++]=ch)) ;
- headerlen = i ;
- if(strcmp(compversion,version))
- pierr(
- "I003: コンパイラ(Version %s)とバージョンが一致しない\n",compversion) ;
- i = 0 ;
- do { /* プログラム名を読む */
- progname[i] = (char)fgetc(pcofile) ;
- fcheck() ;
- } while(progname[i++]) ;
- headerlen += i ;
-
- while((fi[fileno].fileadr = getw(pcofile)) != -1) {
- fcheck() ;
- headerlen += sizeof(short) ;
- fi[fileno].filesize = getw(pcofile) ; /* バッファ変数の大きさ */
- headerlen += sizeof(short) ;
- i = 0 ;
- do { /* ファイル名を読む */
- fi[fileno].filename[i] = (char)fgetc(pcofile) ;
- fcheck() ;
- } while(fi[fileno].filename[i++]) ;
- fi[fileno].mode = undefined ; /* ファイルモードは不定 */
- fi[fileno].askflag = true ; /* ファイル名問い合わせ要としておく*/
- fi[fileno].textfile = false ; /* テキストでないとしておく */
-
- headerlen += i ;
- fileno++ ;
- }
- fcheck() ;
-
- headerlen += sizeof(short) ;
- objsize -= headerlen ;
- fread((char*)store,objsize,1,pcofile) ; /* P-codeオブジェクトを読む*/
- objsize /= sizeof(_store) ;
-
- for(i=0;i<fileno;i++) {
- fi[i].fileadr += objsize ; /* ファイルアドレスの修正 */
- fi[i].filebuf = store + fi[i].fileadr ; /* バッファ変数アドレス*/
- }
- }
-
- /******************************************/
- /* main() : P-codeインタプリタメイン処理 */
- /******************************************/
- void main(int argc,char **argv)
- {
- short i,j ;
- boolean getfileflag = false ;
-
- wargc = argc ;
- wargv = argv ;
-
- if(argc < 2) usage(normal); /* アーギュメントなしはusage */
-
- while(--argc) { /* オプションの処理 */
- if(**++argv == '-') {
- for(i=1;*(*argv+i)!='\0';i++)
- switch(*(*argv+i)) {
- case 'I' :
- case 'i' : infor = true ; /* information option */
- break ;
- case 'T' :
- case 't' : trace = true ; /* trace option */
- break ;
- default : usage(abnormal); /* -t -i 以外はエラー */
- }
- if(i==1) usage(abnormal); /* - だけの時はusage */
- }
- else if(**argv == '/') {
- if((*(*argv+1) == 'f') || (*(*argv+1) == 'F')) {
- j=2 ;
- while((*(*argv+j)) && /* /f・・・・=・・・・・ であること */
- (*(*argv+j)!='=')) j++ ; /* をチェックする */
- if((*(*argv+j)!='=') || /* = がない */
- !(*(*argv+j+1)) || /* = で終わっている */
- (j==2)) usage(abnormal) ; /* /f のみ */
- fileoptflag = true ; /* /fオプション あり */
- }
- }
- else { /* - / から始まらないアーギュメント */
- if(getfileflag) { /* すでにソースファイル名を */
- usage(abnormal); /* 取得している時は 誤り */
- break ; /* whileループ脱出 */
- }
- getfileflag = true ; /* ファイル名取得済とする */
- *pcofname = '\0' ;
- strcpy(pcofname, *argv) ;
- j=0 ; /* 拡張子が省略されているか */
- while((*(pcofname+j)!='\0') && (*(pcofname+j)!='.')) j++ ;
- if(*(pcofname+j)=='\0') strcat(pcofname,ext) ; /* 拡張子を付与 */
- }
- }
-
- if(getfileflag) { /* ファイル名が指定された時 */
- pcofile = fopen(pcofname,"rb");
- if(pcofile==NULL)
- pierr("I001: P-codeオブジェクトファイル(%s)がない\n",pcofname);
- }
- else usage(abnormal) ; /* ファイル名の指定がない時 */
-
- init() ; /* 各種初期設定 */
-
- if(fileoptflag) /* /fオプションあり */
- while(--wargc)
- if(**++wargv == '/')
- if((*(*wargv+1) == 'f') || (*(*wargv+1) == 'F'))
- fileoption(*wargv+2) ;
-
- if(fileno!=fno) inputfilename() ; /* 全ファイルが決定していない時 */
-
- if(infor) information() ; /* -i インタプリタ情報出力 */
-
-
- signal(SIGINT,cntl_c) ; /* CTRL-Cシグナル登録 */
- signal(SIGFPE,real_err) ; /* 実数演算シグナル登録 */
-
- pc = 0 ; /* Program Counter 初期設定 */
- mp = objsize ; /* mp 初期設定 */
- ep = mp + 5 ; /* ep 初期設定 */
- np = Maxstore ; /* np 初期設定 */
- sp = store+mp-1 ; /* Stack Pointer 初期設定 */
-
- interpret() ; /* P-code命令解釈実行 */
- }